wasm4pm-compat 26.6.22

Minimal paper-complete, feature-capped Rust process-evidence crate. Start with compatibility. Graduate to execution.
import { readdir, readFile } from "fs/promises";
import { execSync } from "child_process";
import { existsSync } from "fs";
import { join } from "path";
import { notFound } from "next/navigation";
import { RunButton } from "@/app/_components/RunButton";

// RSC + static generation.
// Runs the pre-compiled binary from target/debug/examples/<name> if it exists,
// falling back to `cargo run` (slow, only on cold cache).
// Output is real binary stdout — no mocking, no fixtures.

const CRATE_ROOT = join(process.cwd(), "..");

export async function generateStaticParams() {
  const dir = join(CRATE_ROOT, "examples");
  const files = await readdir(dir);
  return files
    .filter((f) => f.endsWith(".rs"))
    .map((f) => ({ name: f.replace(".rs", "") }));
}

interface RunResult {
  stdout: string;
  exitCode: number;
  durationMs: number;
  ranVia: "binary" | "cargo" | "none";
}

function runExample(name: string, featureFlag: string | null): RunResult {
  // Prefer the pre-compiled binary — avoids 2-minute recompile in CI.
  const binaryPath = join(CRATE_ROOT, "target", "debug", "examples", name);
  const start = Date.now();

  if (existsSync(binaryPath)) {
    try {
      const raw = execSync(binaryPath, {
        encoding: "utf-8",
        timeout: 30_000,
      });
      return {
        stdout: raw.trim(),
        exitCode: 0,
        durationMs: Date.now() - start,
        ranVia: "binary",
      };
    } catch (e: unknown) {
      const err = e as { stdout?: string; stderr?: string; status?: number };
      return {
        stdout: ((err.stdout ?? "") + (err.stderr ?? "")).trim(),
        exitCode: err.status ?? 1,
        durationMs: Date.now() - start,
        ranVia: "binary",
      };
    }
  }

  // Fall back to cargo run (slow but faithful).
  const cmd = featureFlag
    ? `cargo run --example ${name} --features ${featureFlag}`
    : `cargo run --example ${name}`;
  try {
    const raw = execSync(`${cmd} 2>&1`, {
      cwd: CRATE_ROOT,
      encoding: "utf-8",
      timeout: 180_000,
    });
    const lines = raw.split("\n");
    const runIdx = lines.reduce(
      (last: number, line: string, i: number) =>
        line.trimStart().startsWith("Running `") ? i : last,
      -1
    );
    const output = (runIdx >= 0 ? lines.slice(runIdx + 1) : lines)
      .join("\n")
      .trim();
    return { stdout: output, exitCode: 0, durationMs: Date.now() - start, ranVia: "cargo" };
  } catch (e: unknown) {
    const err = e as { stdout?: string; stderr?: string; status?: number };
    return {
      stdout: ((err.stdout ?? "") + (err.stderr ?? "")).trim(),
      exitCode: err.status ?? 1,
      durationMs: Date.now() - start,
      ranVia: "cargo",
    };
  }
}

export default async function ExamplePage({
  params,
}: {
  params: Promise<{ name: string }>;
}) {
  const { name } = await params;

  const filePath = join(CRATE_ROOT, "examples", `${name}.rs`);
  let source: string;
  try {
    source = await readFile(filePath, "utf-8");
  } catch {
    notFound();
  }

  const lines = source.split("\n");
  const docLines = lines
    .filter((l: string) => l.startsWith("//!"))
    .map((l: string) => l.replace(/^\/\/! ?/, ""));
  const docTitle = docLines[0]?.trim() ?? name;
  const docBody = docLines.slice(1).filter(Boolean).join("\n").trim();

  const featureMatch = source.match(
    /`(formats|strict|wasm4pm)`.*feature|feature.*`(formats|strict|wasm4pm)`/i
  );
  const featureFlag = featureMatch ? featureMatch[1] || featureMatch[2] : null;

  const result = runExample(name, featureFlag);

  const exitColor = result.exitCode === 0 ? "text-emerald-400" : "text-red-400";
  const exitBadge =
    result.exitCode === 0
      ? "bg-emerald-950 border-emerald-800 text-emerald-400"
      : "bg-red-950 border-red-800 text-red-400";

  return (
    <div className="max-w-4xl">
      <nav className="text-xs text-zinc-600 mb-4 font-mono">
        <a href="/examples" className="hover:text-zinc-400">examples</a>
        <span className="mx-1">/</span>
        <span className="text-zinc-400">{name}</span>
      </nav>

      <h1 className="text-2xl font-bold font-mono text-emerald-400 mb-1">{name}</h1>
      {docTitle && docTitle !== name && (
        <p className="text-zinc-300 text-sm mb-1">{docTitle}</p>
      )}
      <div className="flex flex-wrap gap-3 items-center text-xs text-zinc-600 mb-6">
        <span>{lines.length} lines</span>
        {featureFlag && (
          <span className="font-mono text-blue-400 bg-blue-950/50 border border-blue-900 px-1.5 py-0.5 rounded">
            --features {featureFlag}
          </span>
        )}
        <span className="font-mono text-zinc-500">cargo run --example {name}</span>
      </div>

      <section className="mb-8">
        <div className="flex items-center gap-3 mb-2">
          <h2 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider">
            Real binary output
          </h2>
          <span className={`text-xs font-mono px-2 py-0.5 rounded border ${exitBadge}`}>
            EXIT {result.exitCode}
          </span>
          <span className="text-xs text-zinc-600">{result.durationMs}ms via {result.ranVia}</span>
        </div>
        <pre className={`text-xs font-mono bg-zinc-950 border border-zinc-800 rounded p-4 overflow-x-auto whitespace-pre-wrap ${exitColor}`}>
          {result.stdout || "(no stdout)"}
        </pre>
      </section>

      {docBody && (
        <section className="mb-8">
          <h2 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-2">
            Documentation
          </h2>
          <div className="text-sm text-zinc-400 bg-zinc-900 border border-zinc-800 rounded p-4 whitespace-pre-wrap font-mono">
            {docBody}
          </div>
        </section>
      )}

      {/* Server action: re-run the example binary on demand */}
      <RunButton name={name} />

      <section className="mt-8">
        <h2 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-2">
          Source ({lines.length} lines)
        </h2>
        <pre className="text-xs font-mono bg-zinc-950 border border-zinc-800 rounded p-4 overflow-x-auto text-zinc-400 max-h-96 overflow-y-auto whitespace-pre">
          {source}
        </pre>
      </section>
    </div>
  );
}